
package com.publicstaticdroid.g2l_interpreter_connect;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.TextView;
import android.telephony.TelephonyManager;
import android.telephony.PhoneStateListener;

/**
 * MakeCallActivity registers a G2L message blocker, and phone state listener then launches the call activity.
 * When the call ends the phone state listener is triggered and this activity sends a call complete SMS back to the server.
 * @author Nathan Breit
 */
public class MakeCallActivity extends Activity {
	
	private Uri numberToCall;
	private int requestID;
	private long callDuration;
	private Date firstCallStartTime;

	private SMSReceiver messageBlocker;
	private boolean makingCall = false;
	private static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";

	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);

		Log.i("G2L", "MakeCallActivity onCreate");
		
		if(!getIntent().hasExtra("requestID")){
			Log.i("G2L", "MakeCallActivity has no requestID");
			finish();
		}
		
		requestID = getIntent().getIntExtra("requestID", -1);
		numberToCall = getIntent().getData();
		
		setContentView(R.layout.after_call);
		firstCallStartTime = new Date();
		makeCall();
	}
	@Override
	protected void onResume() {
		super.onResume();
		updateStats();
	}
	private void updateStats() {
		TextView interpretationTimeView = (TextView) findViewById(R.id.interpretationTime);
		interpretationTimeView.setText("Call Length: " + callDuration/(1000) + " seconds");
	}
	private void makeCall() {
		
		registerMessageBlocker();
		registerCallListener();
		
		//Delay the call activity to prevent the immediate hang-up bug on the Magic
		Timer timing = new Timer();
		timing.schedule(new TimerTask() {

			@Override
			public void run() {

				runOnUiThread(new Runnable() {

					@Override
					public void run() {

						Log.e("G2L", "Making call");
						try {
							makingCall = true;
							Intent callIntent = new Intent(Intent.ACTION_CALL);
							callIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);//Doubt this does what I want
							//which is make the call activity go back to this one after the call ends.
							callIntent.setData(numberToCall);
							startActivity(callIntent);
						} catch (ActivityNotFoundException activityException) {
							Log.e("G2L", "Call failed");
							finish();
						}
					}
				});
			}
		}, 1000);
	}
	/**
	 * Registers a SMSReciever that intercepts all G2L texts,
	 * and blocks interpretation requests and call commands.
	 */
	private void registerMessageBlocker() {
		//Register a G2L message blocker.
		messageBlocker = new SMSReceiver();
		final IntentFilter theFilter = new IntentFilter();
		theFilter.setPriority(800); //Make sure that all messages are intercepted by the blocker first
		theFilter.addAction(SMS_RECEIVED_ACTION);
		registerReceiver(messageBlocker, theFilter);
	}
	private void unregisterMessageBlocker() {
		try{
			unregisterReceiver(messageBlocker);
			Log.i("G2L", "Unregistering call messageBlocker.");
		}
		catch(IllegalArgumentException e){
			Log.e("G2L", "Unregistering unregistered reciever.");
		}
	}
	/**
	 * This registers a listener that watches the phoneline for a duration of one call.
	 */
	private void registerCallListener() {
		
		//TODO: There are some issues here, if the interpreter redials though the phone app, we will not know who they are calling
		//		Can I bring this app to focus when the call ends?
		
		// Get the telephony manager
		final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

		// Create a new PhoneStateListener
		PhoneStateListener listener = new PhoneStateListener() {

			private boolean phoneWasOffhook = false;
			private Date callStartTime;

			@Override
			public void onCallStateChanged(int state, String incomingNumber) {
				Log.i("G2L", "Number: " + incomingNumber);
				String stateString = "N/A";
				switch (state) {
				case TelephonyManager.CALL_STATE_IDLE:
					if(phoneWasOffhook){
						stateString = "Hangup Happend";
						telephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
						onHangup(new Date().getTime() - callStartTime.getTime());
						//It might be wise to have a timeout for this...
					}
					else{
						stateString = "Idle";
					}
					break;
				case TelephonyManager.CALL_STATE_OFFHOOK:
					stateString = "Off Hook";
					phoneWasOffhook = true;
					callStartTime = new Date();
					break;
				case TelephonyManager.CALL_STATE_RINGING:
					stateString = "Ringing";
					break;
				}
				Log.i("G2L", "Phone State: " + stateString);
			}
		};

		// Register the listener wit the telephony manager
		telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);

		Log.i("G2L", "Call Listener Registered");
	}
	//This might be better handled using on activity result?
	private void onHangup(long lastCallDuration) {
		
		makingCall = false;

		//unregisterMessageBlocker(); I'm going to count on finish for this
		callDuration += lastCallDuration;
		unregisterMessageBlocker();
		
		//Since I'm already in the activity maybe there is a better way to do this?
		Intent BringThisToFrontIntent = new Intent(getApplicationContext(), MakeCallActivity.class);
		//BringThisToFrontIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
		startActivity(BringThisToFrontIntent);
		
		/*
		Intent afterCallIntent = new Intent(getApplicationContext(), AfterCallActivity.class);
		afterCallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		afterCallIntent.putExtra("callDuration", lastCallDuration);
		afterCallIntent.putExtra("requestID", requestID);
		afterCallIntent.setData(numberToCall);
		startActivity(afterCallIntent);
		finish();
		*/
	}
	//Linked directly to button in after_call.xml
	public void redial(View view) {
		makeCall();
	}
	//Linked directly to button in after_call.xml
	//Should do the same thing as pressing home or back.
	public void done(View view) {
		SharedPreferences settings = getSharedPreferences(Constants.PREFS_KEY, 0);
		SharedPreferences.Editor editor = settings.edit();
		editor.putLong("interpretationTime", callDuration + settings.getLong("interpretationTime", 0));
		SMSSender texter = new SMSSender(Constants.SERVER_PHONE);
		texter.sendFinished(requestID, callDuration, firstCallStartTime.getTime(), new Date().getTime());
		finish();
	}
	@Override
	protected void onPause() {
		if( !makingCall ){
			Log.i("G2L", "Checking to see if onPause gets called multiple times somehow.");
			//Terminate the activity if the interpreter navigates away from it.
			done(null);
		}
		super.onPause();
	}
	
	@Override
	protected void onDestroy() {
		unregisterMessageBlocker();
		super.onDestroy();
	}
}